#include "myiic.h"
#include "gd32f20x_eval.h"
#include "gd32f20x.h"
#include "tmp75.h"
#include "gd32f20x_it.h"
#include "systick.h"
#include <rtthread.h>

#define TMP75_ADDRESS1 0x48        // TMP75 地址 位号U6
#define TMP75_ADDRESS2 0x4E        // TMP75 地址 位号U10
#define TMP75_REG_TEMPERATURE 0x00 // 温度寄存器地址
#define TMP75_REG_CONFIG 0x01      // 配置寄存器地址

_myiic_t tmp75_iic = {
    .sclport = IIC_SCL_GPIO_PORT,
    .sdaport = IIC_SDA_GPIO_PORT,
    .sclpin = IIC_SCL_GPIO_PIN,
    .sdapin = IIC_SDA_GPIO_PIN};

/**
 * @brief 初始化IIC
 */
void tempture_iic_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOC);

    gpio_init(IIC_SCL_GPIO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, IIC_SCL_GPIO_PIN);
    gpio_init(IIC_SDA_GPIO_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, IIC_SDA_GPIO_PIN);
}
INIT_APP_EXPORT(tempture_iic_init);

/**
 * @brief 写入 TMP75 寄存器
 * @param address: TMP75 I2C 地址
 */
void tmp75_write_register(_myiic_t *i2c, uint8_t address, uint8_t reg, uint16_t data)
{
    iic_start(i2c);
    iic_send_byte(i2c, address << 1); // 发送器件地址（写模式）
    if (iic_wait_ack(i2c))
        return;
    iic_send_byte(i2c, reg);
    if (iic_wait_ack(i2c))
        return;
    iic_send_byte(i2c, (data >> 8) & 0xFF);
    if (iic_wait_ack(i2c))
        return;
    iic_send_byte(i2c, data & 0xFF);
    if (iic_wait_ack(i2c))
        return;
    iic_stop(i2c);
}

/**
 * @brief 读取 TMP75 寄存器
 * @param address: TMP75 I2C 地址
 */
uint16_t tmp75_read_register(_myiic_t *i2c, uint8_t address, uint8_t reg)
{
    uint16_t value = 0;

    iic_start(i2c);
    iic_send_byte(i2c, address << 1); // 写模式
    if (iic_wait_ack(i2c))
        return 0xFFFF;
    iic_send_byte(i2c, reg);
    if (iic_wait_ack(i2c))
        return 0xFFFF;

    iic_start(i2c);
    iic_send_byte(i2c, (address << 1) | 1); // 读模式
    if (iic_wait_ack(i2c))
        return 0xFFFF;

    value = iic_read_byte(i2c, 1);
    value = (value << 8) | iic_read_byte(i2c, 0);
    iic_stop(i2c);

    return value;
}

/**
 * @brief 读取温度值（摄氏度）
 */
float tmp75_read_temperature(_myiic_t *i2c, uint8_t address)
{
    uint16_t raw_data = tmp75_read_register(i2c, address, TMP75_REG_TEMPERATURE);
    if (raw_data == 0xFFFF)
        return -273.15;
    return (raw_data >> 4) * 0.0625;
}

/**
 * @brief 初始化 TMP75
 */
void tmp75_init(_myiic_t *i2c, uint8_t address)
{
    tmp75_write_register(i2c, address, TMP75_REG_CONFIG, 0x60A0);
    rt_kprintf("tmp75 (0x%02X) config ok\r\n", address);
}

/**
 * @brief 测试两个 TMP75 芯片
 */
void tempture_test(void)
{
    // 初始化IIC
    tempture_iic_init();
    rt_thread_mdelay(100);

    // 初始化两个传感器
    tmp75_init(&tmp75_iic, TMP75_ADDRESS1);
    tmp75_init(&tmp75_iic, TMP75_ADDRESS2);

    // 读取两个温度
    float temp1 = tmp75_read_temperature(&tmp75_iic, TMP75_ADDRESS1);
    float temp2 = tmp75_read_temperature(&tmp75_iic, TMP75_ADDRESS2);

    rt_kprintf("TMP75[0x%02X] = %d.%02d C\r\n", TMP75_ADDRESS1, (int)temp1, ((int)(temp1 * 100)) % 100);
    rt_kprintf("TMP75[0x%02X] = %d.%02d C\r\n", TMP75_ADDRESS2, (int)temp2, ((int)(temp2 * 100)) % 100);
}

MSH_CMD_EXPORT(tempture_test, i2c read two TMP75 temperature);
